﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;

namespace NFinal.Middleware.Resources.Helper
{
    public class ResourcesWriter
    {
        private string projectDiretory;
        private Encoding encoding=new UTF8Encoding(false,false);
        private ResourcesXmlConfig resourcesConfig;
        public ResourcesWriter(string projectDiretory, ResourcesXmlConfig resourcesConfig)
        {
            this.projectDiretory = projectDiretory;
            this.resourcesConfig = resourcesConfig;
        }
        public void Write()
        {
            string resourceFileName;
            string resourceRootDirectory;
            if (resourcesConfig.textResources.Length > 0)
            {
                for (int i = 0; i < resourcesConfig.textResources.Length; i++)
                {
                    resourceFileName = Path.Combine(projectDiretory, resourcesConfig.textResources[i].fileName);
#if NETCORE
                    using (System.Resources.ResourceWriter resourceWriter = new System.Resources.ResourceWriter(File.OpenWrite(resourceFileName)))
#else
                    using (System.Resources.ResourceWriter resourceWriter = new System.Resources.ResourceWriter(resourceFileName))
#endif
                    {
                        for (int j = 0; j < resourcesConfig.textResources[i].includes.Length; j++)
                        {
                            string[] localPaths = resourcesConfig.textResources[i].includes[j].localPath.Split('/');
                            localPaths[0] = projectDiretory;
                            resourceRootDirectory = Path.Combine(localPaths);
                            WriteDirectory(resourceWriter, resourceRootDirectory, resourcesConfig.textResources[i]);
                        }
                        resourceWriter.Generate();
                    }
                }
            }
            if (resourcesConfig.streamResources.Length > 0)
            {
                for (int i = 0; i < resourcesConfig.streamResources.Length; i++)
                {
                    resourceFileName = Path.Combine(projectDiretory, resourcesConfig.streamResources[i].fileName);
#if NETCORE
                    using (System.Resources.ResourceWriter resourceWriter = new System.Resources.ResourceWriter(File.OpenWrite(resourceFileName)))
#else
                    using (System.Resources.ResourceWriter resourceWriter = new System.Resources.ResourceWriter(resourceFileName))
#endif
                    {
                        for (int j = 0; j < resourcesConfig.streamResources[i].includes.Length; j++)
                        {
                            string[] localPaths = resourcesConfig.streamResources[i].includes[j].localPath.Split('/');
                            localPaths[0] = projectDiretory;
                            resourceRootDirectory = Path.Combine(localPaths);
                            WriteDirectory(resourceWriter, resourceRootDirectory, resourcesConfig.streamResources[i]);
                        }
                        resourceWriter.Generate();
                    }
                }
            }
        }
        public string GetRelativeFileName(string rootDiretory,string fileName)
        {
            string path= fileName.Substring(rootDiretory.Length);
            string[] paths= path.Split(new[] { Path.DirectorySeparatorChar ,Path.AltDirectorySeparatorChar}, StringSplitOptions.RemoveEmptyEntries);
            path = string.Join("/", paths);
            return path;
        }
        public bool isExclude(string relativeFileName, Exclude[] excludes)
        {
            if (excludes.Length > 0)
            {
                for (int i = 0; i < excludes.Length; i++)
                {
                    if (ResourcesHelper.IsMatchByPtr(relativeFileName, excludes[i].localPath))
                    {
                        return true;
                    }
                }
            }
            //if (includes.Length > 0)
            //{
            //    for (int i = 0; i < includes.Length; i++)
            //    {
            //        if (ResoucesHelper.IsMatchByPtr(relativeFileName, includes[i].localPath))
            //        {
            //            return true;
            //        }
            //    }
            //}
            return false;
        }
        public void WriteDirectory(System.Resources.ResourceWriter resourceWriter, string rootDirectoryName,StreamResource streamResource)
        {
            string[] direcotryNames = Directory.GetDirectories(rootDirectoryName);
            string[] fileNames = Directory.GetFiles(rootDirectoryName);
            
            string extension;
            string relativeFileName;
            foreach (var fileName in fileNames)
            {
                extension = Path.GetExtension(fileName);
                if (!streamResource.extensions.Contains(extension))
                {
                    continue;
                }
                relativeFileName = GetRelativeFileName(rootDirectoryName,fileName);
                if (isExclude(relativeFileName, streamResource.excludes))
                {
                    continue;
                }
                WriteFile(resourceWriter, fileName,relativeFileName,false);
            }
            foreach (var directoryName in direcotryNames)
            {
                WriteDirectory(resourceWriter, directoryName,streamResource);
            }
        }
        public void WriteDirectory(System.Resources.ResourceWriter resourceWriter, string rootDirectoryName, TextResource textResource)
        {
            string[] direcotryNames = Directory.GetDirectories(rootDirectoryName);
            string[] fileNames = Directory.GetFiles(rootDirectoryName);

            string extension;
            string relativeFileName;
            foreach (var fileName in fileNames)
            {
                extension = Path.GetExtension(fileName);
                if (!textResource.extensions.Contains(extension))
                {
                    continue;
                }
                relativeFileName = GetRelativeFileName(rootDirectoryName, fileName);
                if (isExclude(relativeFileName, textResource.excludes))
                {
                    continue;
                }
                WriteFile(resourceWriter, fileName, relativeFileName, true);
            }
            foreach (var directoryName in direcotryNames)
            {
                WriteDirectory(resourceWriter, directoryName, textResource);
            }
        }
        public void WriteFile(System.Resources.ResourceWriter resourceWriter,string fileName,string relativeFileName,bool isText)
        {
            if (isText)
            {
                string text = null;
#if NETCORE
                using (StreamReader streamReader = File.OpenText(fileName))
                {
                    text = streamReader.ReadToEnd();
                }
#else
                using (StreamReader streamReader = new StreamReader(fileName))
                {
                    text = streamReader.ReadToEnd();
                }
#endif
                    resourceWriter.AddResource(relativeFileName, text);
            }
            else
            {
                byte[] buffer = null;
                using (FileStream fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read))
                {
                    buffer = new byte[fileStream.Length];
                    fileStream.Read(buffer, 0, buffer.Length);
                    fileStream.Dispose();
                }
                if (buffer != null)
                {
#if NETCORE
                    resourceWriter.AddResource(relativeFileName,System.Convert.ToBase64String(buffer));
#else
                    resourceWriter.AddResource(relativeFileName,System.Convert.ToBase64String(buffer));
#endif
                }
            }
        }
    }
}
